package com.xinqi.modules.discuss.discuss.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.xinqi.common.base.enums.YesNoNumberEnum;
import com.xinqi.common.base.response.PageInfo;
import com.xinqi.common.base.response.Param;
import com.xinqi.common.base.response.R;
import com.xinqi.common.core.enums.DiscussReleaseStatusEnum;
import com.xinqi.common.mybatis.data.service.impl.BaseServiceImpl;
import com.xinqi.common.mybatis.utils.Pages;
import com.xinqi.modules.course.clazz.client.ClassStudentClient;
import com.xinqi.modules.course.clazz.dto.rsp.ClassStudentResultDTO;
import com.xinqi.modules.discuss.discuss.domain.CourseDiscussEntity;
import com.xinqi.modules.discuss.discuss.domain.CourseDiscussStudentLogEntity;
import com.xinqi.modules.discuss.discuss.dto.req.CourseDiscussStudentLogQueryDTO;
import com.xinqi.modules.discuss.discuss.dto.rsp.CourseDiscussResultDTO;
import com.xinqi.modules.discuss.discuss.dto.rsp.CourseDiscussStudentLogResultDTO;
import com.xinqi.modules.discuss.discuss.mapper.CourseDiscussStudentLogMapper;
import com.xinqi.modules.discuss.discuss.service.CourseDiscussStudentLogService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 服务层实现
 *
 * @author: yyzhen
 * @date: 2023/03/13
 */
@Service("courseDiscussStudentLogService")
@RequiredArgsConstructor
public class CourseDiscussStudentLogServiceImpl extends BaseServiceImpl<CourseDiscussStudentLogMapper, CourseDiscussStudentLogEntity> implements CourseDiscussStudentLogService {

    @Lazy
    private final ClassStudentClient classStudentClient;

    /**
     * 已参与列表/未参与列表
     *
     * @param pageable
     * @param query
     * @return
     */
    @Override
    @DS("slaver")
    public PageInfo<CourseDiscussStudentLogResultDTO> selectPage(Param pageable, CourseDiscussStudentLogQueryDTO query) {
        IPage<CourseDiscussStudentLogResultDTO> pageData = this.baseMapper.selectPage1(Pages.page(pageable), query);
        return Pages.convert(pageData);
    }

    /**
     * 根据讨论ID删除
     *
     * @Title:
     * @MethodName: deleteByContentId
     * [contentId]
     * @Return void
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/3/16 10:34
     */
    @Override
    public void deleteByContentId(Long contentId) {
        this.baseMapper.delete(new LambdaQueryWrapper<CourseDiscussStudentLogEntity>().eq(CourseDiscussStudentLogEntity::getContentId, contentId));
    }

    @Override
    public void deleteByContentIds(List<Long> contentIds) {
        this.baseMapper.delete(new LambdaQueryWrapper<CourseDiscussStudentLogEntity>().in(CourseDiscussStudentLogEntity::getContentId, contentIds));
    }

    /**
     * 根据讨论ID和学生ID获取参与情况
     *
     * @Title:
     * @MethodName: selectByContentIdAndStudentId
     * [contentId, studentId]
     * @Return com.xinqi.modules.discuss.discuss.domain.CourseDiscussStudentLogEntity
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/3/15 20:03
     */
    @Override
    public CourseDiscussStudentLogEntity selectByContentIdAndStudentId(Long contentId, Long studentId) {
        LambdaUpdateWrapper<CourseDiscussStudentLogEntity> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(CourseDiscussStudentLogEntity::getContentId, contentId).eq(CourseDiscussStudentLogEntity::getStudentId, studentId).last("limit 1");
        return this.baseMapper.selectOne(wrapper);
    }

    /**
     * 根据讨论ID集合和学生ID获取列表
     *
     * @Title:
     * @MethodName: selectByContentIdAndStudentId
     * [contentIds, studentId]
     * @Return java.util.List<com.xinqi.modules.discuss.discuss.domain.CourseDiscussStudentLogEntity>
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/4/5 18:06
     */
    @Override
    public List<CourseDiscussStudentLogEntity> selectByContentIdAndStudentId(List<Long> contentIds, Long studentId) {
        LambdaUpdateWrapper<CourseDiscussStudentLogEntity> wrapper = new LambdaUpdateWrapper<>();
        wrapper.in(CourseDiscussStudentLogEntity::getContentId, contentIds).eq(CourseDiscussStudentLogEntity::getStudentId, studentId);
        return this.baseMapper.selectList(wrapper);
    }

    /**
     * 通过讨论ID获取列表
     *
     * @Title:
     * @MethodName: selectByContentId
     * [contentId]
     * @Return java.util.List<com.xinqi.modules.discuss.discuss.domain.CourseDiscussStudentLogEntity>
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/4/5 14:55
     */
    @Override
    public List<CourseDiscussStudentLogEntity> selectByContentId(Long contentId) {
        LambdaUpdateWrapper<CourseDiscussStudentLogEntity> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(CourseDiscussStudentLogEntity::getContentId, contentId);
        return this.baseMapper.selectList(wrapper);
    }

    /**
     * 同步学生设置（学生日志记录不影响主业务，但存在数据量大的情况，故采用异步处理）
     * 去掉线程池防止线程池过大导致系统奔溃-dzy
     *
     * @param entity
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void synchroStudent(CourseDiscussEntity entity) {
        if (Objects.isNull(entity)) {
            return;
        }

        // 查询班级内的所有成员
        List<ClassStudentResultDTO> students = this.getSyncStudent(entity);
        if (CollectionUtils.isEmpty(students)) {
            return;
        }

        //获取所有学生记录，防止重复
        List<CourseDiscussStudentLogEntity> logEntityList = this.selectByContentId(entity.getId());
        Map<Long, CourseDiscussStudentLogEntity> logEntityMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(logEntityList)) {
            logEntityList.forEach(logEntity -> {
                logEntityMap.put(logEntity.getStudentId(), logEntity);
            });
        }
        List<CourseDiscussStudentLogEntity> list = new ArrayList<>();
        //同步班级成员讨论内容
        students.forEach(student -> {
            if (!logEntityMap.containsKey(student.getStudentId())
                && !Objects.equals(entity.getCreateBy(), student.getStudentId())) {
                //无数据
                CourseDiscussStudentLogEntity studentLogEntity = new CourseDiscussStudentLogEntity();
                studentLogEntity.setContentId(entity.getId());
                studentLogEntity.setStudentId(student.getStudentId());
                studentLogEntity.setClassId(entity.getClassId());
                studentLogEntity.setIsRead(YesNoNumberEnum.NO.getCode());
                studentLogEntity.setIsPartake(YesNoNumberEnum.NO.getCode());
                list.add(studentLogEntity);
            }

        });
        //同步班级成员讨论内容
        if (CollectionUtils.isNotEmpty(list)) {
            this.saveBatch(list);
        }
    }

    /**
     * 同步学生设置（学生日志记录不影响主业务，但存在数据量大的情况，故采用异步处理）
     *
     * @param discussList
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void synchroStudent(List<CourseDiscussEntity> discussList) {
        if (CollectionUtils.isEmpty(discussList)) {
            return;
        }
        //返回结果
        List<CourseDiscussStudentLogEntity> studentLogList = new ArrayList<>();
        discussList.forEach(discuss -> {
            // 获取主学生信息
            ClassStudentResultDTO mainStudent = R.as(classStudentClient.findVirtualClassStudentByClassIdAndUserId(discuss.getClassId(), discuss.getCreateBy()));
            if (Objects.nonNull(mainStudent)) {
                discuss.setCreateBy(mainStudent.getStudentId());
            }

            // 查询班级内的所有成员
            List<ClassStudentResultDTO> students = R.as(classStudentClient.findContainsTeacherListByClassId(discuss.getClassId()));
            // 检索老师、助教和模拟学生
            students = students.stream().filter(v -> Objects.equals(YesNoNumberEnum.NO.getCode(), v.getIsRelationalStudent())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(students)) {
                return;
            }
            //获取所有学生记录，防止重复
            List<CourseDiscussStudentLogEntity> logEntityList = this.selectByContentId(discuss.getId());
            Map<Long, CourseDiscussStudentLogEntity> logEntityMap = new HashMap<>();
            if (CollectionUtils.isNotEmpty(logEntityList)) {
                logEntityList.forEach(logEntity -> {
                    logEntityMap.put(logEntity.getStudentId(), logEntity);
                });
            }
            //同步班级成员讨论内容
            students.forEach(student -> {
                if (!logEntityMap.containsKey(student.getStudentId())
                    && !Objects.equals(discuss.getCreateBy(), student.getStudentId())) {
                    //无数据
                    CourseDiscussStudentLogEntity studentLogEntity = new CourseDiscussStudentLogEntity();
                    studentLogEntity.setContentId(discuss.getId());
                    studentLogEntity.setStudentId(student.getStudentId());
                    studentLogEntity.setClassId(discuss.getClassId());
                    //创建即已读
                    if (Objects.equals(discuss.getCreateBy(), student.getStudentId())) {
                        studentLogEntity.setIsRead(YesNoNumberEnum.YES.getCode());
                    } else {
                        studentLogEntity.setIsRead(YesNoNumberEnum.NO.getCode());
                    }
                    studentLogEntity.setIsPartake(YesNoNumberEnum.NO.getCode());
                    studentLogList.add(studentLogEntity);
                }
            });
        });
        if (CollectionUtils.isNotEmpty(studentLogList)) {
            this.saveBatch(studentLogList);
        }

    }

    /**
     * 新增学生同步（学生日志记录不影响主业务，但存在数据量大的情况，故采用异步处理）
     *
     * @param discussList
     * @param classId
     * @param userId
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void synchroStudent(List<CourseDiscussEntity> discussList, Long classId, Long userId) {
        if (CollectionUtils.isEmpty(discussList)) {
            return;
        }
        //返回结果
        List<CourseDiscussStudentLogEntity> studentLogList = new ArrayList<>();
        // 查询成员

        ClassStudentResultDTO student = R.as(classStudentClient.findByStudentId(classId, userId));
        if (Objects.isNull(student)) {
            return;
        }
        List<Long> contentIds = discussList.stream().map(CourseDiscussEntity::getId).collect(Collectors.toList());
        //获取所有学生记录，防止重复
        List<CourseDiscussStudentLogEntity> logEntityList = this.selectByContentIdAndStudentId(contentIds, userId);
        Map<Long, CourseDiscussStudentLogEntity> logEntityMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(logEntityList)) {
            logEntityList.forEach(logEntity -> {
                logEntityMap.put(logEntity.getContentId(), logEntity);
            });
        }
        discussList.forEach(discuss -> {
            if (!logEntityMap.containsKey(discuss.getId())) {
                CourseDiscussStudentLogEntity studentLogEntity = new CourseDiscussStudentLogEntity();
                studentLogEntity.setContentId(discuss.getId());
                studentLogEntity.setStudentId(userId);
                studentLogEntity.setClassId(classId);
                studentLogEntity.setIsRead(YesNoNumberEnum.NO.getCode());
                studentLogEntity.setIsPartake(YesNoNumberEnum.NO.getCode());
                studentLogList.add(studentLogEntity);
            }

        });
        if (CollectionUtils.isNotEmpty(studentLogList)) {
            this.saveBatch(studentLogList);
        }
    }

    /**
     * 已读
     *
     * @param result
     * @param userId
     */
    @Override
    public void synchroRead(CourseDiscussResultDTO result, Long userId) {
        if (Objects.isNull(result)) {
            return;
        }
        ClassStudentResultDTO student = R.as(classStudentClient.findByStudentId(result.getClassId(), userId));
        if (Objects.isNull(student)) {
            return;
        }
        // 获取关系 模拟主学生信息
        ClassStudentResultDTO mainStudent = R.as(classStudentClient.findVirtualClassStudentByClassIdAndUserId(result.getClassId(), userId));
        CourseDiscussStudentLogEntity studentLogEntity = null;
        if (Objects.nonNull(mainStudent)) {
            // 校验发布人信息
            ClassStudentResultDTO publishStudent = R.as(classStudentClient.findVirtualClassStudentByClassIdAndUserId(result.getClassId(), result.getCreateBy()));
            // 不为空 学生发布 判断是否是自己查看
            if (Objects.nonNull(publishStudent)) {
                if (Objects.equals(publishStudent.getStudentId(), mainStudent.getStudentId())) {
                    return;
                }
            }
            // 学生获取 日志记录
            studentLogEntity = this.selectByContentIdAndStudentId(result.getId(), mainStudent.getStudentId());
        } else{
            // 老师助教获取 判断是否是自己查看
            if (Objects.equals(result.getCreateBy(), userId)) {
                return;
            }
            // 老师助教获取 日志记录
            studentLogEntity = this.selectByContentIdAndStudentId(result.getId(), userId);
        }

        if (Objects.isNull(studentLogEntity)) {
            // 判断是否已结束
            if (!Objects.equals(DiscussReleaseStatusEnum.CLOSED.getCode(), result.getStatus())) {
                studentLogEntity = new CourseDiscussStudentLogEntity();
                studentLogEntity.setClassId(result.getClassId());
                studentLogEntity.setContentId(result.getId());
                studentLogEntity.setStudentId(userId);
                //进行中 -- 已读，  未发布 -- 未读
                if (Objects.equals(DiscussReleaseStatusEnum.IN_PROGRESS.getCode(), result.getStatus())) {
                    studentLogEntity.setIsRead(YesNoNumberEnum.YES.getCode());
                } else {
                    studentLogEntity.setIsRead(YesNoNumberEnum.NO.getCode());
                }
                studentLogEntity.setIsPartake(YesNoNumberEnum.NO.getCode());

                this.save(studentLogEntity);
            }
        } else {
            //已发布 -- 可完成已读
            if (Objects.equals(DiscussReleaseStatusEnum.IN_PROGRESS.getCode(), result.getStatus()) && Objects.equals(YesNoNumberEnum.NO.getCode(), studentLogEntity.getIsRead())) {
                studentLogEntity.setIsRead(YesNoNumberEnum.YES.getCode());

                this.updateById(studentLogEntity);
            }
        }
    }

    /**
     * 获取同步学生的信息
     */
    public List<ClassStudentResultDTO> getSyncStudent(CourseDiscussEntity discuss) {
        // 获取发布人信息
        ClassStudentResultDTO publishStudent = R.as(classStudentClient.findByStudentId(discuss.getClassId(), discuss.getCreateBy()));
        // 获取全部学生信息
        List<ClassStudentResultDTO> allStudent = R.as(classStudentClient.findContainsTeacherListByClassId(discuss.getClassId()));

        if (Objects.equals(YesNoNumberEnum.YES.getCode(), publishStudent.getIsTeacher())) {
            // 去掉发布 老师信息
            allStudent = allStudent.stream().filter(v -> !Objects.equals(publishStudent.getStudentId(), v.getStudentId())).collect(Collectors.toList());
            // 去掉关系用户信息
            allStudent = allStudent.stream().filter(v -> !Objects.equals(YesNoNumberEnum.YES.getCode(), v.getIsRelationalStudent())).collect(Collectors.toList());
            return allStudent;
        } else {
            // 去掉虚拟学生相关用户信息
            allStudent = allStudent.stream().filter(v -> !Objects.equals(publishStudent.getPatStuRefId(), v.getPatStuRefId())
                && !Objects.equals(publishStudent.getPatStuRefId(), v.getStudentId())).collect(Collectors.toList());
            // 去掉关系用户信息
            allStudent = allStudent.stream().filter(v -> !Objects.equals(YesNoNumberEnum.YES.getCode(), v.getIsRelationalStudent())
                || Objects.equals(YesNoNumberEnum.YES.getCode(), v.getIsTeacher())).collect(Collectors.toList());
            return allStudent;
        }
    }

}
